package com.taoz.rpc.core.server;

import com.taoz.rpc.core.config.ApplicationConfig;
import com.taoz.rpc.core.model.RpcRequest;
import com.taoz.rpc.core.model.RpcResponse;
import com.taoz.rpc.core.registry.LocalRegistry;
import com.taoz.rpc.core.serializer.Serializer;
import com.taoz.rpc.core.serializer.SerializerFactory;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.lang.reflect.Method;

@Slf4j
public class VertxHttpRequestHandler implements Handler<HttpServerRequest> {
    @Override
    public void handle(HttpServerRequest httpServerRequest) {
        httpServerRequest.bodyHandler(body -> {
            Serializer serializer = null;
            try {
                serializer = SerializerFactory.getSerializer(ApplicationConfig.getConfig().getSerializer());
            } catch (Exception e) {
                log.info("获取序列化器失败");
                return;
            }
            RpcRequest rpcRequest = null;
            try {
                rpcRequest = serializer.deserialize(body.getBytes(), RpcRequest.class);
            } catch (Exception e) {
                log.info("Deserialize fail");
            }
            RpcResponse rpcResponse = new RpcResponse();
            if (rpcRequest == null) {
                rpcResponse.setMessage("rpcRequest is null");
                doResponse(httpServerRequest, rpcResponse, serializer);
                return;
            }
            try {
                Class<?> clazz = LocalRegistry.get(rpcRequest.getServiceName());
                Method method = clazz.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
                Object result = method.invoke(clazz.newInstance(), rpcRequest.getArgs());
                rpcResponse.setData(result);
                rpcResponse.setMessage("ok");
                rpcResponse.setDataType(method.getReturnType());
                doResponse(httpServerRequest, rpcResponse, serializer);
            } catch (Exception e) {
                rpcResponse.setMessage(e.getMessage());
                doResponse(httpServerRequest, rpcResponse, serializer);
            }
        });
    }

    public void doResponse(HttpServerRequest httpServerRequest, RpcResponse rpcResponse, Serializer serializer) {
        HttpServerResponse response = httpServerRequest.response();
        try {
            byte[] bytes = serializer.serialize(rpcResponse);
            response.end(Buffer.buffer(bytes));
        } catch (IOException e) {
            log.info("序列化失败");
            response.end(Buffer.buffer());
        }
    }
}
